import {
  EChartsOption,
  SeriesOption,
  XAXisComponentOption,
  YAXisComponentOption,
  ECElementEvent,
} from 'echarts';
import {
  IChartXAxis,
  IChartYAxis,
  IDEChart,
  IDEChartLegend,
  IDEChartTitle,
} from '@ibiz/model-core';
import { mergeDeepRight } from 'ramda';
import { CodeListItem } from '@ibiz-template/runtime';
import { RuntimeError } from '@ibiz-template/core';
import { BaseSeriesGenerator } from './base-series-generator';
import { LineSeriesGenerator } from './line-series-generator';
import { BarSeriesGenerator } from './bar-series-generator';
import { FunnelSeriesGenerator } from './funnel-series-generator';
import { PieSeriesGenerator } from './pie-series-generator';
import { ScatterSeriesGenerator } from './scatter-series-generator';
import { RadarCoordSystem } from './radar-coord-system';
import { RadarSeriesGenerator } from './radar-series-generator';

/**
 * 解析userParams
 * @author lxm
 * @date 2023-06-09 09:03:07
 * @export
 * @param {Record<string, string>} userParams
 * @return {*}
 */
export function parseUserParams(userParams: Record<string, string>): IData {
  const option: IData = {};
  if (userParams) {
    Object.keys(userParams).forEach(key => {
      const index = key.indexOf('.');
      if (index === -1) {
        return;
      }
      const customKey = key.slice(index + 1);
      if (customKey) {
        try {
          option[customKey] = JSON.parse(userParams[key]);
        } catch (error) {
          option[customKey] = userParams[key];
        }
      }
    });
  }
  return option;
}

export class ChartOptionsGenerator {
  /**
   * 根据模型配置算出来的静态echarts配置
   * @author lxm
   * @date 2023-06-07 09:50:44
   * @type {EChartsOption}
   */
  staticOptions: EChartsOption = {
    tooltip: {
      show: true,
    },
  };

  /**
   * 最终计算产物
   * @author lxm
   * @date 2023-06-08 09:23:40
   * @type {EChartsOption}
   */
  options: EChartsOption = {};

  /**
   * 图表整体的自定义Options
   * @author lxm
   * @date 2023-06-09 08:59:40
   * @type {EChartsOption}
   */
  chartUserParam?: EChartsOption;

  /**
   * 序列生成器集合
   * @author lxm
   * @date 2023-06-09 05:47:41
   * @type {BaseSeriesGenerator[]}
   */
  seriesGenerators: BaseSeriesGenerator[] = [];

  /**
   * 雷达坐标系映射
   * key是分类属性，值是雷达坐标的序号
   * @author lxm
   * @date 2023-06-08 03:51:03
   */
  radarMap = new Map<string, RadarCoordSystem>();

  /**
   * 缓存已经加载的代码表数据
   * @author lxm
   * @date 2023-06-09 07:47:35
   */
  codeListMap: Map<string, Readonly<CodeListItem[]>> = new Map();

  constructor(private model: IDEChart) {
    this.initSeriesGenerators();
    const {
      dechartTitle,
      dechartLegend,
      chartXAxises,
      chartYAxises,
      userParam,
    } = model;

    // 标题
    if (dechartTitle) {
      this.staticOptions.title = this.calcTitleOption(dechartTitle);
    }

    // 图例
    if (dechartLegend) {
      this.staticOptions.legend = this.calcLegendOption(dechartLegend);
    }
    // x轴
    if (chartXAxises?.length) {
      this.staticOptions.xAxis = this.calcXYAxisOption(
        chartXAxises,
      ) as XAXisComponentOption[];
    }
    // y轴
    if (chartYAxises?.length) {
      this.staticOptions.yAxis = this.calcXYAxisOption(
        chartYAxises,
      ) as YAXisComponentOption[];
    }

    if (userParam) {
      this.chartUserParam = parseUserParams(userParam);
    }
  }

  protected initSeriesGenerators(): void {
    this.model.dechartSerieses?.forEach(series => {
      let seriesGenerator;
      switch (series.seriesType) {
        case 'line':
          seriesGenerator = new LineSeriesGenerator(series, this);
          break;
        case 'bar':
          seriesGenerator = new BarSeriesGenerator(series, this);
          break;
        case 'scatter':
          seriesGenerator = new ScatterSeriesGenerator(series, this);
          break;
        case 'pie':
          seriesGenerator = new PieSeriesGenerator(series, this);
          break;
        case 'funnel':
          seriesGenerator = new FunnelSeriesGenerator(series, this);
          break;
        case 'radar':
          seriesGenerator = new RadarSeriesGenerator(series, this);
          break;
        default:
          ibiz.log.error(`图表暂未支持序列类型${series.seriesType}`);
          break;
      }
      if (seriesGenerator) {
        this.seriesGenerators.push(seriesGenerator);
      }
    });
  }

  protected calcTitleOption(chartTitle: IDEChartTitle): EChartsOption['title'] {
    const { showTitle, title, subTitle, titlePos } = chartTitle;
    const titleOption: EChartsOption['title'] = {
      show: showTitle,
      text: title,
      subtext: subTitle,
    };

    // 标题位置
    titleOption.left = 'center';
    const position = titlePos?.toLowerCase();
    if (position === 'left' || position === 'right') {
      titleOption.left = position;
    } else if (position === 'bottom' || position === 'top') {
      titleOption.top = position;
    }
    return titleOption;
  }

  protected calcLegendOption(
    chartLegend: IDEChartLegend,
  ): EChartsOption['legend'] {
    const { showLegend, legendPos } = chartLegend;
    const legendOption: EChartsOption['legend'] = {};
    legendOption.show = showLegend;
    const position = legendPos?.toLowerCase();
    if (position === 'left' || position === 'right') {
      legendOption.left = position;
      legendOption.top = 'middle';
      legendOption.orient = 'vertical';
    } else if (position === 'bottom') {
      legendOption.top = position;
    }
    return legendOption;
  }

  protected calcXYAxisOption(
    chartAxises: IChartYAxis[] | IChartXAxis[],
  ): XAXisComponentOption[] | YAXisComponentOption[] {
    const AxisOption: EChartsOption['xAxis'] | EChartsOption['yAxis'] = [];
    chartAxises.forEach(chartAxis => {
      const { position, dataShowMode, userParam } = chartAxis;
      let option = {
        type: chartAxis.echartsType,
        name: chartAxis.caption,
        max: chartAxis.maxValue,
        min: chartAxis.minValue,
        position,
        axisLabel: {
          formatter: (value: string): string => {
            if (dataShowMode === 1) {
              if (value.length > 4) {
                return `${value.slice(0, 4).split('').join('\n')}\n...`;
              }
              return value.split('').join('\n');
            }
            if (dataShowMode === 2) {
              if (value.length > 4) {
                return `${value.slice(0, 4)}...`;
              }
            }
            return value;
          },
          rotate: dataShowMode === 3 ? 45 : 0,
        },
      };

      // 有自定义参数的合并自定义参数
      if (userParam) {
        option = mergeDeepRight(option, parseUserParams(userParam));
      }

      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      AxisOption.push(option as any);
    });
    return AxisOption;
  }

  /**
   * 加载代码表，
   * - 如果已经加载过会清空缓存重新加载
   * - 相同的代码表之后加载一次
   * @author lxm
   * @date 2023-06-09 08:05:28
   * @param {IContext} context
   * @param {IParams} params
   * @return {*}  {Promise<void>}
   */
  async loadCodeList(context: IContext, params: IParams): Promise<void> {
    // 先清空缓存;
    this.codeListMap.clear();
    if (!this.model.dechartSerieses?.length) {
      return;
    }

    const app = ibiz.hub.getApp(context.srfappid);
    const loadCodeList = async (key: string | undefined): Promise<void> => {
      if (!key || this.codeListMap.has(key)) {
        return;
      }
      const codeListItems = await app.codeList.get(key, context, params);
      this.codeListMap.set(key, codeListItems);
    };

    await Promise.all(
      this.model.dechartSerieses.map(async series => {
        const { seriesCodeListId, catalogCodeListId } = series;
        await loadCodeList(seriesCodeListId);
        await loadCodeList(catalogCodeListId);
      }),
    );
  }

  /**
   * 根据数据计算出最终的options
   * @author lxm
   * @date 2023-06-09 08:10:52
   * @param {IData[]} data
   * @return {*}  {EChartsOption}
   */
  calcOptionsByData(data: IData[]): EChartsOption {
    // 清空操作
    this.radarMap.clear();
    this.options = {
      series: [],
      radar: [],
    };

    // 雷达图表先计算坐标系
    this.seriesGenerators.forEach(generator => {
      if (generator.model.seriesType === 'radar') {
        (generator as RadarSeriesGenerator).calcRadarCoordSystem(data);
      }
    });
    // 生成雷达坐标系
    if (this.radarMap.size) {
      this.options.radar = [...this.radarMap.values()].map(radar =>
        radar.toOptions(),
      );
    }

    // 生成seriesOptions
    const seriesOption: SeriesOption[] = [];
    this.seriesGenerators.forEach(generator => {
      const series = generator.calcByData(data);
      if (series instanceof Array) {
        seriesOption.push(...series);
      } else {
        seriesOption.push(series);
      }
    });
    this.options.series = seriesOption;

    // 合并静态和动态的options
    this.options = mergeDeepRight(
      this.staticOptions,
      this.options,
    ) as EChartsOption;

    // 有自定义参数的合并自定义参数
    if (this.chartUserParam) {
      this.options = mergeDeepRight(
        this.options,
        this.chartUserParam,
      ) as EChartsOption;
    }

    return this.options;
  }

  getSrfkeyByParams(params: ECElementEvent): string {
    const generator = this.seriesGenerators[params.seriesIndex!];
    if (!generator) {
      throw new RuntimeError(`找不到${params.seriesIndex}序列的generator！`);
    }
    return generator.getSrfkeyByParams(params);
  }

  // protected calcRadarSeries(data: IData[], series: IChartSeriesFunnel) {
  //   // 初始化radarMap
  //   let radarIndex = this.radarMap.size; // 默认新坐标系的索引
  //   let radarMapObj: Record<string, number>;
  //   if (this.radarMap.has(catalogField)) {
  //     radarMapObj = this.radarMap.get(catalogField)!;
  //     radarIndex = radarMapObj.radarIndex;
  //   } else {
  //     radarMapObj = {
  //       radarIndex,
  //     };
  //     this.radarMap.set(catalogField, radarMapObj);
  //   }

  //   // 雷达坐标系维度顺序
  //   let indicatorKeys: string[] = [];
  //   if (Object.values(radarMapObj).length > 1) {
  //     indicatorKeys = Object.keys(radarMapObj).slice(1);
  //   }

  //   // 生成雷达数据，多个分组在一起
  //   const radarData = Object.keys(groupChartData).map(group => {
  //     // 处理每个序列的数据
  //     const catalogData = groupChartData[group];
  //     if (indicatorKeys.length === 0) {
  //       indicatorKeys = Object.keys(catalogData);
  //     }

  //     const value = indicatorKeys.map(key => {
  //       // 更新radar坐标系的最大值
  //       if (
  //         radarMapObj[key] === undefined ||
  //         radarMapObj[key] < catalogData[key]
  //       ) {
  //         radarMapObj[key] = catalogData[key];
  //       }
  //       return catalogData[key];
  //     });

  //     return {
  //       value,
  //       name: group !== 'default' ? group : seriesName,
  //     };
  //   });

  //   const seriesOption: SeriesOption = {
  //     type: 'radar',
  //     ...this.seriesDefaultOptions,
  //     radarIndex,
  //     data: radarData,
  //   };

  //   return seriesOption;
  // }
}
